#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/mmc/dw_mmc.h>
#include <linux/clk.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
#include <linux/phy.h>
#include <linux/dma-mapping.h>
#include <linux/spi/eeprom.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/if_alg.h>
#include <linux/mmc/host.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <mach/pmu.h>
#include <mach/io.h>
#include <mach/board_config.h>
#include <mach/pinctrl.h>
#include <mach/clock.h>
#include <mach/fh_uart_plat.h>
#include <mach/fh_mci_plat.h>
#include <mach/fh_gmac_plat.h>
#include <mach/fh_gpio_plat.h>
#include <mach/fh_efuse_plat.h>
#include <mach/fh_dma_plat.h>
#include <mach/fh_spi_plat.h>
#include <mach/fh_i2s_plat.h>
#include <mach/fh_pwm_plat.h>
#include <mach/fh_wdt_plat.h>
#include <mach/fh_usb_plat.h>
#include <mach/fh_sadc_plat.h>
#include <mach/fh_rtc_plat.h>
#include "chip.h"
#include <linux/gpio.h>
#include <linux/irqchip/arm-gic.h>
#include <mach/platsmp.h>
#include "iotable.h"

struct uart_port fh_serial_ports[FH_UART_NUMBER] = {0};
static void *va_ephy;
static struct resource fh_gpio0_resources[] = {
	{
		.start		= GPIO0_REG_BASE,
		.end		= GPIO0_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},

	{
		.start		= GPIO0_IRQ,
		.end		= GPIO0_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};

static struct resource fh_gpio1_resources[] = {
	{
		.start		= GPIO1_REG_BASE,
		.end		= GPIO1_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},

	{
		.start		= GPIO1_IRQ,
		.end		= GPIO1_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};

static struct resource fh_gpio2_resources[] = {
	{
		.start		= GPIO2_REG_BASE,
		.end		= GPIO2_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},

	{
		.start		= GPIO2_IRQ,
		.end		= GPIO2_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};

static struct resource fh_uart0_resources[] = {
	{
		.start		= (UART0_REG_BASE),
		.end		= (UART0_REG_BASE) + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},

	{
		.start		= UART0_IRQ,
		.end		= UART0_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};

static struct resource fh_uart1_resources[] = {
	{
		.start		= (UART1_REG_BASE),
		.end		= (UART1_REG_BASE) + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},
	{
		.start		= UART1_IRQ,
		.end		= UART1_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};
static struct resource fh_uart2_resources[] = {
	{
		.start		= (UART2_REG_BASE),
		.end		= (UART2_REG_BASE) + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},
	{
		.start		= UART2_IRQ,
		.end		= UART2_IRQ,
		.flags		= IORESOURCE_IRQ,
	}
};
static struct resource fh_uart3_resources[] = {
	{
		.start		= (UART3_REG_BASE),
		.end		= (UART3_REG_BASE) + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},
	{
		.start		= UART3_IRQ,
		.end		= UART3_IRQ,
		.flags		= IORESOURCE_IRQ,
	}
};
static struct resource fh_sdc0_resources[] = {
	{
		.start		= SDC0_REG_BASE,
		.end		= SDC0_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},
	{
		.start		= SDC0_IRQ,
		.end		= SDC0_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};
static struct resource fh_sdc1_resources[] = {
	{
		.start		= SDC1_REG_BASE,
		.end		= SDC1_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},
	{
		.start		= SDC1_IRQ,
		.end		= SDC1_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};

static struct resource fh_gmac_resources[] = {
	{
		.start		= GMAC_REG_BASE,
		.end		= GMAC_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},

	{
		.start		= GMAC_IRQ,
		.end		= GMAC_IRQ,
		.flags		= IORESOURCE_IRQ,
	}
};

static struct resource fh_wdt_resources[] = {
	{
		.start		= WDT_REG_BASE,
		.end		= WDT_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},
	{
		.start		= WDT_IRQ,
		.end		= WDT_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};

#if defined(CONFIG_FH_PERF_MON) || defined(CONFIG_FH_PERF_MON_V2)
static struct resource fh_perf_resources[] = {
		{
			.start	= PERF_REG_BASE,
			.end	= PERF_REG_BASE + SZ_16K - 1,
			.flags	= IORESOURCE_MEM,
		},
		{
			.start	= PERF_IRQ,
			.end	= PERF_IRQ,
			.flags	= IORESOURCE_IRQ,
		},
};
#endif

#ifdef CONFIG_FH_STEPMOTOR
static struct resource fh_stepmotor_resources0[] = {
		{
			.start          = STM0_REG_BASE,
			.end            = STM0_REG_BASE + SZ_16K - 1,
			.flags          = IORESOURCE_MEM,
		},
		{
			.start          = STM_H_IRQ,
			.end            = STM_H_IRQ,
			.flags          = IORESOURCE_IRQ,
		},
};

static struct resource fh_stepmotor_resources1[] = {
		{
			.start          = STM1_REG_BASE,
			.end            = STM1_REG_BASE + SZ_16K - 1,
			.flags          = IORESOURCE_MEM,
		},
		{
			.start          = STM_V_IRQ,
			.end            = STM_V_IRQ,
			.flags          = IORESOURCE_IRQ,
		},
};

#endif


struct phy_reg_cfg phy_config_array[] = {
	{
		.id = FH_GMAC_PHY_RTL8201,
		.list = {
			{W_PHY, 0x1f, 0x7},
			{W_PHY, 0x10, 0x1ffa},
			{W_PHY, 0x1f, 0},
			{W_PHY, 0x0d, 0x07},
			{W_PHY, 0x0e, 0x3c},
			{W_PHY, 0x0d, 0x4007},
			{W_PHY, 0x0e, 0x0},
			{0},
		},
		.inf_sup = PHY_INTERFACE_MODE_RMII,
	},
	{
		.id = FH_GMAC_PHY_IP101G,
		.list = {
			{W_PHY, 0x14, 0x10},
			{W_PHY, 0x10, 0x1006},
			{W_PHY, 0x14, 0x10},
			{0},
		},
		.inf_sup = PHY_INTERFACE_MODE_RMII,
	},
	{
		.id = FH_GMAC_PHY_TI83848,
		.list = {
			{M_PHY, 0x11, 0x20, 0x20},
			{0},
		},
		.inf_sup = PHY_INTERFACE_MODE_RMII,
	},
	{
		.id = FH_GMAC_PHY_DUMMY,
		.list = {
			{0},
		},
		.inf_sup = PHY_INTERFACE_MODE_RMII,
	},
	{
		.id = FH_GMAC_PHY_INTERNAL_V2,
		.list = {
			{0},
		},
		.inf_sup = PHY_INTERFACE_MODE_MII,
	},
	{
		.id = FH_GMAC_PHY_RTL8211F,
		.list = {
			{0},
		},
		.inf_sup = PHY_INTERFACE_MODE_RGMII,
		.dll_enable = DLL_SETTING_ENABLE,
	},
	{
		.id = FH_GMAC_PHY_JL2101,
		.list = {
			{0},
		},
		.inf_sup = PHY_INTERFACE_MODE_RGMII,
	},
	{
		.id = FH_GMAC_PHY_MAE0621,
		.list = {
			{W_PHY, 0x1f, 0x0d92},
			{W_PHY, 0x1f, 0x0d92},
			{W_PHY, 0x02, 0x200a},
			{W_PHY, 0x1f, 0x0},

			{W_PHY, 0x1f, 0x0},
			{W_PHY, 0x0d, 0x7},
			{W_PHY, 0x0e, 0x3c},
			{W_PHY, 0x0d, 0x4007},
			{W_PHY, 0x0e, 0x0},
			{W_PHY, 0x0, 0x9140},
			{W_PHY, 0x1f, 0x0},

			{0},
		},
		.inf_sup = PHY_INTERFACE_MODE_RGMII,
	},
	{0},
};

void fh_external_phy_reset(void)
{
	int ret;
	int reset_pin = EXTERNAL_PHY_RESET_GPIO;


	/*fh_pmu_set_reg_m(REG_PMU_DLL, 0x8080, 0xffff);*/

	ret = gpio_request(reset_pin, "phyreset-gpio");
	if (ret) {
		pr_err("%s: ERROR: request reset pin : %d failed\n",
		__func__, reset_pin);
		return;
	}

	gpio_direction_output(reset_pin, GPIOF_OUT_INIT_HIGH);
	usleep_range(150000, 200000);
	gpio_direction_output(reset_pin, GPIOF_OUT_INIT_LOW);
	/* actual is 20ms */
	usleep_range(150000, 200000);
	gpio_direction_output(reset_pin, GPIOF_OUT_INIT_HIGH);
	usleep_range(150000, 200000);
	gpio_free(reset_pin);

}

static int phy_inf_set(unsigned int inf)
{

	pr_err("set inf is %x\n", inf);
	if (inf == PHY_INTERFACE_MODE_RMII) {
		/*bit 100 : rmii; bit 000 : mii*/
		fh_pmu_set_reg_m(REG_PMU_GMAC_REG, 4, 7);
	} else if (inf == PHY_INTERFACE_MODE_RGMII) {
		fh_pmu_set_reg_m(REG_PMU_GMAC_REG, 1, 7);
	} else {
		fh_pmu_set_reg_m(REG_PMU_GMAC_REG, 0, 7);
	}

	return 0;
}

static int eth_set_speed(unsigned int speed, void *pri)
{
	/*pr_err("eth_set_speed is [%d]\n", speed);*/
	struct phy_reg_cfg *reg_cfg = (struct phy_reg_cfg *)pri;
	//must be external phy spd set...
	if (reg_cfg->inf_sup == PHY_INTERFACE_MODE_RGMII) {
		//eth_ref_clk_i [25M]
		fh_pmu_set_reg_m(REG_PMU_CLK_DIV4, 3 << 28, 0xf << 28);
		//rgmii_tx_clk_gate	[ungate]
		fh_pmu_set_reg_m(REG_PMU_CLK_GATE1, 0 << 1, 1 << 1);
		//rgmii_tx_clk_polarity
		//fh_pmu_set_reg_m(REG_PMU_CLK_SEL2, 0 << 23, 1 << 23);
		//rgmii_tx_clk_dll
		//fh_pmu_set_reg_m(REG_PMU_DLL, 0 << 7, 0x3f << 7);
		//eth_clk_sel [0]
		fh_pmu_set_reg_m(REG_PMU_CLK_SEL2, 0 << 15, 1 << 15);
		//rgmii_rmii_sel [1]
		fh_pmu_set_reg_m(REG_PMU_CLK_SEL2, 1 << 16, 1 << 16);
		//rgmii_rx_clk_polarity
		//fh_pmu_set_reg_m(REG_PMU_CLK_SEL2, 0 << 24, 1 << 24);
		//rgmii_rx_clk_dll
		//fh_pmu_set_reg_m(REG_PMU_DLL, 0, 0x3f);
		//rgmii_rx_clk_sel [0]
		fh_pmu_set_reg_m(REG_PMU_CLK_SEL2, 0 << 17, 1 << 17);
	} else {
		//eth_ref_clk_i [50M]
		fh_pmu_set_reg_m(REG_PMU_CLK_DIV4, 1 << 28, 0xf << 28);
		//rgmii_tx_clk_gate	[gate]
		fh_pmu_set_reg_m(REG_PMU_CLK_GATE1, 1 << 1, 1 << 1);
		//eth_clk_sel [1]
		fh_pmu_set_reg_m(REG_PMU_CLK_SEL2, 1 << 15, 1 << 15);
		//rgmii_rmii_sel [0]
		fh_pmu_set_reg_m(REG_PMU_CLK_SEL2, 0 << 16, 1 << 16);
		//rgmii_rx_clk_sel [0]
		fh_pmu_set_reg_m(REG_PMU_CLK_SEL2, 0 << 17, 1 << 17);
	}


	switch (speed) {
	case 1000:
		//mac_sed [125M]
		fh_pmu_set_reg_m(REG_PMU_CLK_SEL2, 2 << 12, 3 << 12);
		break;
	case 100:
		//mac_sed
		fh_pmu_set_reg_m(REG_PMU_CLK_SEL2, 1 << 12, 3 << 12);
		break;
	case 10:
		fh_pmu_set_reg_m(REG_PMU_CLK_SEL2, 0 << 12, 3 << 12);
		break;
	}

	return 0;
}

static int phy_sel_func(unsigned int phy_sel)
{
	if (phy_sel == EXTERNAL_PHY) {
		pr_err("BETA :: phy sel external phy with 25M refclk\n");
		//close internal phy
		fh_pmu_set_reg_m(REG_PMU_EPHY_SEL,
		0 << INSIDE_PHY_ENABLE_BIT_POS,
		1 << INSIDE_PHY_ENABLE_BIT_POS);
		//ephy_clk [gate]
		fh_pmu_set_reg_m(REG_PMU_CLK_GATE1, 1 << 3, 1 << 3);
		//eth_ref_clk_out_g [gate]!!!!
		fh_pmu_set_reg_m(REG_PMU_CLK_GATE1, 1 << 0, 1 << 0);
		//eth_ref_clk_i div to [50M]
		//fh_pmu_set_reg_m(REG_PMU_CLK_DIV4, 1 << 28, 0xf << 28);
		// //eth_ref_clk_i div to [25M]
		fh_pmu_set_reg_m(REG_PMU_CLK_DIV4, 3 << 28, 0xf << 28);
		//eth_rmii_clk_g [ungate]
		fh_pmu_set_reg_m(REG_PMU_CLK_GATE1, 0 << 2, 1 << 2);
		//rmii_clk_mode switch [1]
		fh_pmu_set_reg_m(REG_PMU_CLK_SEL2, 1 << 14, 1 << 14);
		//mac speed set [50M]
		fh_pmu_set_reg_m(REG_PMU_CLK_SEL2, 1 << 12, 3 << 12);
		//eth_clk_sel [1]
		fh_pmu_set_reg_m(REG_PMU_CLK_SEL2, 1 << 15, 1 << 15);
		//rgmii_rmii_sel [0]
		fh_pmu_set_reg_m(REG_PMU_CLK_SEL2, 0 << 16, 1 << 16);
		//rgmii_rx_clk_sel [0]
		fh_pmu_set_reg_m(REG_PMU_CLK_SEL2, 0 << 17, 1 << 17);
		//eth_ref_clk_out_g [ungate]!!!!
		fh_pmu_set_reg_m(REG_PMU_CLK_GATE1, 0 << 0, 1 << 0);

	} else {
		pr_err("BETA :: phy sel internal phy\n");
		/*open internal phy*/
		fh_pmu_set_reg_m(REG_PMU_EPHY_SEL,
		1 << INSIDE_PHY_ENABLE_BIT_POS,
		1 << INSIDE_PHY_ENABLE_BIT_POS);
		//ephy_clk  [gate]
		fh_pmu_set_reg_m(REG_PMU_CLK_GATE1, 1 << 3, 1 << 3);
		//eth_ref_clk_out_g [gate]!!!!
		fh_pmu_set_reg_m(REG_PMU_CLK_GATE1, 1 << 0, 1 << 0);
		//eth_rmii_clk_g [gate]
		fh_pmu_set_reg_m(REG_PMU_CLK_GATE1, 1 << 2, 1 << 2);
		//eth_clk_sel				[0]
		fh_pmu_set_reg_m(REG_PMU_CLK_SEL2, 0 << 15, 1 << 15);
		//rgmii_rmii_sel			[0]
		fh_pmu_set_reg_m(REG_PMU_CLK_SEL2, 0 << 16, 1 << 16);
		//rgmii_rx_clk_sel [0]
		fh_pmu_set_reg_m(REG_PMU_CLK_SEL2, 0 << 17, 1 << 17);
		//ephy_clk [ungate]
		fh_pmu_set_reg_m(REG_PMU_CLK_GATE1, 0 << 3, 1 << 3);
		//eth_ref_clk_out_g [ungate]!!!!
		fh_pmu_set_reg_m(REG_PMU_CLK_GATE1, 0 << 0, 1 << 0);
	}

	return 0;
}



void fh_qos_set_phy_dll_val(u32 tx_val, u32 rx_val)
{
	/*pr_err("set dll tx : rx = %x : %x\n",tx_val, rx_val);*/
	fh_pmu_set_reg_m(REG_PMU_DLL,
	tx_val << 8 | rx_val, 0xffff);
}


void fh_qos_set_phy_polarity(u32 tx_pol, u32 rx_pol)
{
	/*pr_err("set polarity tx : rx = %x : %x\n",tx_pol, rx_pol);*/
	fh_pmu_set_reg_m(REG_PMU_CLK_SEL2,
	tx_pol << 23 | rx_pol << 24, 0x3 << 23);
}

void dump_pol_dll_info(struct soc_reg_tuning *p_tuning)
{
	unsigned int id = 0;

	id = p_tuning->id_l | p_tuning->id_m << 8 | p_tuning->id_h << 16;
	pr_err("---ID [%x]---\n", id);
	pr_err("---[1000M]---\n");

	pr_err("\tTX_POL :: %s\n",
	((p_tuning->area_pol >> 3) & 1) == DLL_POL_FWD ? "FWD" : "REV");
	pr_err("\tRX_POL :: %s\n",
	((p_tuning->area_pol >> 2) & 1) == DLL_POL_FWD ? "FWD" : "REV");
	pr_err("\tTX_DLL :: 0x%x\n",
	p_tuning->area_1000_txdll);
	pr_err("\tRX_DLL :: 0x%x\n",
	p_tuning->area_1000_rxdll);

	pr_err("---[100M]---\n");
	pr_err("\tTX_POL :: %s\n",
	((p_tuning->area_pol >> 1) & 1) == DLL_POL_FWD ? "FWD" : "REV");
	pr_err("\tRX_POL :: %s\n",
	((p_tuning->area_pol) & 1) == DLL_POL_FWD ? "FWD" : "REV");
	pr_err("\tTX_DLL :: 0x%x\n",
	p_tuning->area_100_txdll);
	pr_err("\tRX_DLL :: 0x%x\n",
	p_tuning->area_100_rxdll);
}
static void fh_external_phy_link_up_cb(void *pri)
{
	struct mii_bus *p_mii_bus;
	struct phy_device *phydev;
	struct phy_reg_cfg *p_reg_cfg;
	unsigned int tmp[2] = {0};
	struct soc_reg_tuning tuning_val = {0};
	int i;
	unsigned int id = 0;

	p_mii_bus = (struct mii_bus *)pri;
	phydev = mdiobus_get_phy(p_mii_bus, 0);
	if (!phydev)
		return;
	//pr_err("fh_external_phy_link_up_cb speed is %d\n",phydev->speed);
	tmp[0] = fh_pmu_get_reg(REG_PMU_GMAC_TUNING_0);
	tmp[1] = fh_pmu_get_reg(REG_PMU_GMAC_TUNING_1);

	memcpy(&tuning_val, tmp, sizeof(struct soc_reg_tuning));
	dump_pol_dll_info(&tuning_val);
	id = tuning_val.id_l | tuning_val.id_m << 8 | tuning_val.id_h << 16;
	for (i = 0, p_reg_cfg = phy_config_array;
	i < ARRAY_SIZE(phy_config_array); i++, p_reg_cfg++) {
		if (phydev->phy_id == p_reg_cfg->id) {

			if (id == (phydev->phy_id & DLL_ID_MASK)) {
				p_reg_cfg->tx_1000_polarity =
				(tuning_val.area_pol >> 3) & 1;
				p_reg_cfg->rx_1000_polarity =
				(tuning_val.area_pol >> 2) & 1;
				p_reg_cfg->tx_1000_dll_val =
				tuning_val.area_1000_txdll;
				p_reg_cfg->rx_1000_dll_val =
				tuning_val.area_1000_rxdll;
				p_reg_cfg->tx_100_polarity =
				(tuning_val.area_pol >> 1) & 1;
				p_reg_cfg->rx_100_polarity =
				(tuning_val.area_pol) & 1;
				p_reg_cfg->tx_100_dll_val =
				tuning_val.area_100_txdll;
				p_reg_cfg->rx_100_dll_val =
				tuning_val.area_100_rxdll;
				p_reg_cfg->tx_10_polarity =
				p_reg_cfg->tx_100_polarity;
				p_reg_cfg->rx_10_polarity =
				p_reg_cfg->rx_100_polarity;
				p_reg_cfg->tx_10_dll_val =
				p_reg_cfg->tx_100_dll_val;
				p_reg_cfg->rx_10_dll_val =
				p_reg_cfg->rx_100_dll_val;
			}

			if (p_reg_cfg->dll_enable == DLL_SETTING_ENABLE) {
				if (phydev->speed == SPEED_10) {
					fh_qos_set_phy_polarity(
					p_reg_cfg->tx_10_polarity,
					p_reg_cfg->rx_10_polarity);
					fh_qos_set_phy_dll_val(
					p_reg_cfg->tx_10_dll_val,
					p_reg_cfg->rx_10_dll_val);
				}

				else if (phydev->speed == SPEED_100) {
					fh_qos_set_phy_polarity(
					p_reg_cfg->tx_100_polarity,
					p_reg_cfg->rx_100_polarity);
					fh_qos_set_phy_dll_val(
					p_reg_cfg->tx_100_dll_val,
					p_reg_cfg->rx_100_dll_val);
				}

				else if (phydev->speed == SPEED_1000) {
					fh_qos_set_phy_polarity(
					p_reg_cfg->tx_1000_polarity,
					p_reg_cfg->rx_1000_polarity);
					fh_qos_set_phy_dll_val(
					p_reg_cfg->tx_1000_dll_val,
					p_reg_cfg->rx_1000_dll_val);
				}

			} else {
				if (phydev->speed == SPEED_1000)
					pr_err("Warning :: you may need to scan 1000M pll ....\n");
			}
			/*break match id..*/
			break;
		}
	}

}


static void fh_external_phy_link_down_cb(void *pri)
{

}


enum {
	CP_VAL_0,
	CP_VAL_1,
	VAL_100M_0,
	VAL_100M_1,
	VAL_10M_0,
	VAL_10M_1,
	TRAIN_MAX_SIZE,
};

static u32 train_100_array[] = {
	31, 30, 29, 28,
	27, 26, 25, 24,
	23, 22, 21, 20,
	19, 18, 17, 16,
	0,  1,  2,  3,
	4,  5,  6,  7,
	8,  9,  10, 11,
	12, 13, 14, 15,
};

static u32 train_10_array[] = {
	31, 30, 29, 28,
	27, 26, 25, 24,
	23, 22, 21, 20,
	19, 18, 17, 16,
	0,  1,  2,  3,
	4,  5,  6,  7,
	8,  9,  10, 11,
	12, 13, 14, 15,
};

static u32 train_cp_array[] = {
	0, 1, 2, 3,
};
#define REFIX_CP_TRAIN_DATA_OFFSET	    (0)
#define REFIX_100M_TRAIN_DATA_OFFSET    (0)
#define REFIX_10M_TRAIN_DATA_OFFSET	    (0)

struct s_train_val train_array[TRAIN_MAX_SIZE] = {

		[CP_VAL_0].name = "cp_val_0",
		[CP_VAL_0].src_add = REG_PMU_EPHY_PARAM,
		[CP_VAL_0].src_mask = 0xc0,
		[CP_VAL_0].src_vaild_index = 15,
		[CP_VAL_0].dst_add = 0x18,
		[CP_VAL_0].dst_vaild_index = 22,
		[CP_VAL_0].bind_train_array = train_cp_array,
		[CP_VAL_0].bind_train_size = ARRAY_SIZE(train_cp_array),
		[CP_VAL_0].usr_train_offset =
		REFIX_CP_TRAIN_DATA_OFFSET,

		[CP_VAL_1].name = "cp_val_1",
		[CP_VAL_1].src_add = REG_PMU_EPHY_PARAM,
		[CP_VAL_1].src_mask = 0xc0,
		[CP_VAL_1].src_vaild_index = 15,
		[CP_VAL_1].dst_add = 0xb7c,
		[CP_VAL_1].dst_vaild_index = 6,
		[CP_VAL_1].bind_train_array = train_cp_array,
		[CP_VAL_1].bind_train_size = ARRAY_SIZE(train_cp_array),
		[CP_VAL_1].usr_train_offset =
		REFIX_CP_TRAIN_DATA_OFFSET,

		[VAL_100M_0].name = "val_100M_0",
		[VAL_100M_0].src_add = REG_PMU_EPHY_PARAM,
		[VAL_100M_0].src_mask = 0x1f,
		[VAL_100M_0].src_vaild_index = 5,
		[VAL_100M_0].dst_add = 0x24,
		[VAL_100M_0].dst_vaild_index = 8,
		[VAL_100M_0].bind_train_array = train_100_array,
		[VAL_100M_0].bind_train_size = ARRAY_SIZE(train_100_array),
		[VAL_100M_0].usr_train_offset =
		REFIX_100M_TRAIN_DATA_OFFSET,

		[VAL_100M_1].name = "val_100M_1",
		[VAL_100M_1].src_add = REG_PMU_EPHY_PARAM,
		[VAL_100M_1].src_mask = 0x1f,
		[VAL_100M_1].src_vaild_index = 5,
		[VAL_100M_1].dst_add = 0x1308,
		[VAL_100M_1].dst_vaild_index = 8,
		[VAL_100M_1].bind_train_array = train_100_array,
		[VAL_100M_1].bind_train_size = ARRAY_SIZE(train_100_array),
		[VAL_100M_1].usr_train_offset =
		REFIX_100M_TRAIN_DATA_OFFSET,

		[VAL_10M_0].name = "val_10M_0",
		[VAL_10M_0].src_add = REG_PMU_EPHY_PARAM,
		[VAL_10M_0].src_mask = 0x1f00,
		[VAL_10M_0].src_vaild_index = 13,
		[VAL_10M_0].dst_add = 0x24,
		[VAL_10M_0].dst_vaild_index = 16,
		[VAL_10M_0].bind_train_array = train_10_array,
		[VAL_10M_0].bind_train_size = ARRAY_SIZE(train_10_array),
		[VAL_10M_0].usr_train_offset =
		REFIX_10M_TRAIN_DATA_OFFSET,

		[VAL_10M_1].name = "val_10M_1",
		[VAL_10M_1].src_add = REG_PMU_EPHY_PARAM,
		[VAL_10M_1].src_mask = 0x1f00,
		[VAL_10M_1].src_vaild_index = 13,
		[VAL_10M_1].dst_add = 0x1308,
		[VAL_10M_1].dst_vaild_index = 0,
		[VAL_10M_1].bind_train_array = train_10_array,
		[VAL_10M_1].bind_train_size = ARRAY_SIZE(train_10_array),
		[VAL_10M_1].usr_train_offset =
		REFIX_10M_TRAIN_DATA_OFFSET,
};

void dump_phy_train_val(struct s_train_val *p_train)
{
	pr_err("------------GAP_LINE---------------\n");
	pr_err("name            : %s\n", p_train->name);
	pr_err("src_add         : %08x\n", p_train->src_add);
	pr_err("src_mask        : %08x\n", p_train->src_mask);
	pr_err("src_vaild_index : %08x\n", p_train->src_vaild_index);
	pr_err("dst_add         : %08x\n", p_train->dst_add);
	pr_err("dst_vaild_index : %08x\n", p_train->dst_vaild_index);
	pr_err("usr_train_offset: %d\n", p_train->usr_train_offset);
}


void parse_train_data(struct s_train_val *p_train)
{
	unsigned long test_data;
	int i;
	u32 temp_data;
	u32 vaild_bit_pos;
	int max_offset, low_offset;
	u32 *array;
	u32 size;

	if (!va_ephy) {
		pr_err("ioremap internal phy err\n");
		BUG_ON(1);
	}

	array = p_train->bind_train_array;
	size = p_train->bind_train_size;
	test_data = p_train->src_mask;
	vaild_bit_pos = find_first_bit(&test_data, 32);

	if ((!array) ||
	((p_train->src_mask >> vaild_bit_pos) != (size - 1))) {
		pr_err("para error..\n");
		return;
	}

	temp_data = fh_pmu_get_reg(p_train->src_add);
	if (temp_data & (1 << p_train->src_vaild_index)) {
		/*got vaild val*/
		temp_data &= p_train->src_mask;
		temp_data >>= vaild_bit_pos;
		pr_err("[%s] :: train val %d\n", p_train->name, temp_data);
		/*find index*/
		for (i = 0; i < size; i++) {
			if (temp_data == array[i]) {
				max_offset = (size - 1) - i;
				low_offset = 0 - i;
				break;
			}
		}

		if ((p_train->usr_train_offset < low_offset) ||
		(p_train->usr_train_offset > max_offset)) {
			pr_err("offset [%d] should limit in [%d , %d]\n",
			p_train->usr_train_offset, low_offset, max_offset);
			return;
		}
		//fix array idx..
		i += p_train->usr_train_offset;
		temp_data = array[i];
		/*pr_err("fix idx :: [%d] = %d\n", i, temp_data);*/
	} else {
		temp_data = 0;
		pr_err("[%s] :: use default train data %d\n",
		p_train->name, temp_data);
	}
	temp_data &= (p_train->src_mask >> vaild_bit_pos);
	SET_REG_M((u32)va_ephy + p_train->dst_add,
	temp_data << p_train->dst_vaild_index,
	(p_train->src_mask >> vaild_bit_pos) << p_train->dst_vaild_index);
}


static void fh_internal_phy_reset(void)
{
	int idx;
	unsigned int chip_id;

	chip_id = fh_pmu_get_reg(REG_PMU_CHIP_INFO);

	/*just map once*/
	if (!va_ephy)
		va_ephy = ioremap(EPHY_REG_BASE, SZ_16K);

	if (!va_ephy) {
		pr_err("ioremap internal phy err\n");
		BUG_ON(1);
	}

	SET_REG_M((u32)va_ephy + 0, 0, 0x3<<7);
	SET_REG((u32)va_ephy + 0x28, 0x00247875);
	SET_REG((u32)va_ephy + 0x1274, 0x3c3);

	fh_pmu_set_reg_m(REG_PMU_CLK_GATE1, 0, 1<<0);
	fh_pmu_set_reg_m(REG_PMU_SWRSTN_NSR, 0, 1<<23);
	fh_pmu_set_reg_m(REG_PMU_SWRST_APB_CTRL, 0, 1<<27);
	udelay(200);
	fh_pmu_set_reg_m(REG_PMU_SWRST_APB_CTRL, 1<<27, 1<<27);
	fh_pmu_set_reg_m(REG_PMU_SWRSTN_NSR, 1<<23, 1<<23);

	SET_REG_M((u32)va_ephy + 0x1370, 0x0, 1<<3);
	SET_REG((u32)va_ephy + 0x1274, 0x3c3);
	SET_REG((u32)va_ephy + 0x0b6C, 0xf04);
	SET_REG((u32)va_ephy + 0x1340, 0x0000);
	SET_REG((u32)va_ephy + 0x0bA8, 0x20);
	SET_REG((u32)va_ephy + 0x0018, 0x00c02800);
	SET_REG((u32)va_ephy + 0x001c, 0x00810000);
	SET_REG((u32)va_ephy + 0x0020, 0x0000340c);
	if (chip_id == 0x00400009) {
		//xgmp
		SET_REG((u32)va_ephy + 0x0024, 0x30131500);
	} else {
		//xgm
		SET_REG((u32)va_ephy + 0x0024, 0x10131500);
	}
	SET_REG((u32)va_ephy + 0x0028, 0x01402800);
	SET_REG((u32)va_ephy + 0x001c, 0xa1800000);
	SET_REG((u32)va_ephy + 0x0028, 0x00402800);
	SET_REG((u32)va_ephy + 0x0014, 0x06000000);
	SET_REG((u32)va_ephy + 0x0020, 0x2340c);
	SET_REG((u32)va_ephy + 0x000c, 0xba0edfff);
	SET_REG((u32)va_ephy + 0x0010, 0x7fcbf9de);
	SET_REG((u32)va_ephy + 0x0b98, 0xd150);
	SET_REG((u32)va_ephy + 0x1224, 0);
	SET_REG((u32)va_ephy + 0x12f0, 0);
	SET_REG((u32)va_ephy + 0x0bc0, 0x7de);
	SET_REG((u32)va_ephy + 0x0bc8, 0x09de);
	SET_REG((u32)va_ephy + 0x070c, 0x0401);
	SET_REG((u32)va_ephy + 0x0a84, 0x1d20);
	SET_REG((u32)va_ephy + 0x06d4, 0x3130);
	SET_REG((u32)va_ephy + 0x0a6c, 0x0818);
	SET_REG((u32)va_ephy + 0x0aec, 0x1000);
	SET_REG((u32)va_ephy + 0x0658, 0x1c00);
	SET_REG((u32)va_ephy + 0x07d4, 0x6900);
	SET_REG((u32)va_ephy + 0x06b8, 0x4);
	SET_REG((u32)va_ephy + 0x06E4, 0x04a0);
	SET_REG((u32)va_ephy + 0x0BBC, 0x1759);
	SET_REG((u32)va_ephy + 0x0bf8, 0x0100);
	SET_REG((u32)va_ephy + 0x0794, 0x9000);
	SET_REG((u32)va_ephy + 0x0788, 0xf);
	if (chip_id == 0x00400009) {
		//xgmp
		SET_REG((u32)va_ephy + 0x1378, 0x1e26);
	} else{
		//xgm
		SET_REG((u32)va_ephy + 0x1378, 0x1820);
	}
	SET_REG_M((u32)va_ephy + 0x0, 0x20<<24, 0xff<<24);
	SET_REG_M((u32)va_ephy + 0x4, 0x18, 0xff);
	SET_REG((u32)va_ephy + 0x0680, 0x0552);
	SET_REG((u32)va_ephy + 0x1274, 0);
	SET_REG((u32)va_ephy + 0x0b6C, 0x704);
	SET_REG((u32)va_ephy + 0x1340, 0);
	SET_REG((u32)va_ephy + 0x0ba8, 0);
	SET_REG((u32)va_ephy + 0x06c8, 0xc000);
	SET_REG((u32)va_ephy + 0x06e0, 0x8508);
	SET_REG((u32)va_ephy + 0x1328, 0x0065);
	SET_REG((u32)va_ephy + 0x076c, 0x0430);
	SET_REG((u32)va_ephy + 0x06b4, 0xfd00);
	SET_REG((u32)va_ephy + 0x1360, 0x3f37);
	SET_REG_M((u32)va_ephy + 0x0778, 0x24 << 8, 0xff << 8);
	SET_REG_M((u32)va_ephy + 0x077c, 0x24, 0xff);
	SET_REG((u32)va_ephy + 0xb10, 0x5000);
	SET_REG((u32)va_ephy + 0xb14, 0x8000);
	SET_REG((u32)va_ephy + 0xb1c, 0x000e);
	SET_REG((u32)va_ephy + 0xb20, 0x000e);
	SET_REG((u32)va_ephy + 0xb1c, 0x000f);
	SET_REG((u32)va_ephy + 0xb20, 0x0035);
	SET_REG((u32)va_ephy + 0xb1c, 0x0000);
	SET_REG((u32)va_ephy + 0xb10, 0x0000);
	SET_REG((u32)va_ephy + 0xb14, 0x0000);
	/*led*/
	SET_REG((u32)va_ephy + 0x2c, 0x13);
	SET_REG_M((u32)va_ephy + 0x07f8, 3 << 8, 3 << 8);

	for (idx = 0; idx < ARRAY_SIZE(train_array); idx++) {
		/*dump_phy_train_val(&train_array[idx]);*/
		parse_train_data(&train_array[idx]);
	}

}


static void fh_internal_phy_link_up_cb(void *pri)
{
	if (!va_ephy) {
		pr_err("ioremap internal phy err\n");
		BUG_ON(1);
	}

	SET_REG((u32)va_ephy + 0x0b10, 0x5000);
	SET_REG((u32)va_ephy + 0x0b14, 0x8000);
	SET_REG((u32)va_ephy + 0x0b1c, 0x000e);
	SET_REG((u32)va_ephy + 0x0b20, 0x0004);
	SET_REG((u32)va_ephy + 0x0aec, 0x1800);
	SET_REG((u32)va_ephy + 0x0b10, 0x0000);
	SET_REG((u32)va_ephy + 0x0b14, 0x0000);
}

static void fh_internal_phy_link_down_cb(void *pri)
{
	if (!va_ephy) {
		pr_err("ioremap internal phy err\n");
		BUG_ON(1);
	}

	SET_REG((u32)va_ephy + 0xb10, 0x5000);
	SET_REG((u32)va_ephy + 0xb14, 0x8000);
	SET_REG((u32)va_ephy + 0xb1c, 0x000e);
	SET_REG((u32)va_ephy + 0xb20, 0x000e);
	SET_REG((u32)va_ephy + 0xb1c, 0x000f);
	SET_REG((u32)va_ephy + 0xb20, 0x0035);
	SET_REG((u32)va_ephy + 0xb1c, 0x0000);
	SET_REG((u32)va_ephy + 0xb10, 0x0000);
	SET_REG((u32)va_ephy + 0xb14, 0x0000);
}


static struct fh_gmac_platform_data fh_gmac_data = {

	.phy_sel = phy_sel_func,
	.inf_set = phy_inf_set,
	.gmac_reset = 0,
	.p_cfg_array = phy_config_array,
	.phy_info[0] = {
		.phy_sel = EXTERNAL_PHY,
		.phy_inf = PHY_INTERFACE_MODE_RGMII,
		.phy_reset = fh_external_phy_reset,
		.ex_sync_mac_spd = eth_set_speed,
		.brd_link_up_cb = fh_external_phy_link_up_cb,
		.brd_link_down_cb = fh_external_phy_link_down_cb,
	},

	.phy_info[1] = {
		.phy_sel = INTERNAL_PHY,
		.phy_inf = PHY_INTERFACE_MODE_MII,
		.phy_reset = fh_internal_phy_reset,
		.ex_sync_mac_spd = 0,
		.brd_link_up_cb = fh_internal_phy_link_up_cb,
		.brd_link_down_cb = fh_internal_phy_link_down_cb,
	},
};
static struct fh_platform_uart fh_uart_platform_data[] = {
	{
		.mapbase	= UART0_REG_BASE,
		.fifo_size	= 16,
		.irq		= UART0_IRQ,
		.uartclk	= 16666667,
	},
	{
		.mapbase	= UART1_REG_BASE,
		.fifo_size	= 32,
		.irq		= UART1_IRQ,
		.uartclk	= 16666667,
		.flags		= UPF_HARD_FLOW,
	},
	{
		.mapbase	= UART2_REG_BASE,
		.fifo_size	= 32,
		.irq		= UART2_IRQ,
		.uartclk	= 16666667,
	},
	{
		.mapbase	= UART3_REG_BASE,
		.fifo_size	= 32,
		.irq		= UART3_IRQ,
		.uartclk	= 16666667,
	},
};

static struct resource fh_pwm_resources[] = {
	{
		.start		= PWM_REG_BASE,
		.end		= PWM_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},
	{
		.start		= PWM_IRQ,
		.end		= PWM_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};

static struct resource fh_i2c_resources_0[] = {
	{
		.start		= I2C0_REG_BASE,
		.end		= I2C0_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},

	{
		.start		= I2C0_IRQ,
		.end		= I2C0_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};
static struct resource fh_i2c_resources_1[] = {
	{
		.start		= I2C1_REG_BASE,
		.end		= I2C1_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},

	{
		.start		= I2C1_IRQ,
		.end		= I2C1_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};
static struct resource fh_i2c_resources_2[] = {
	{
		.start		= I2C2_REG_BASE,
		.end		= I2C2_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},

	{
		.start		= I2C2_IRQ,
		.end		= I2C2_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};

static struct resource fh_i2c_resources_3[] = {
	{
		.start		= I2C3_REG_BASE,
		.end		= I2C3_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},

	{
		.start		= I2C3_IRQ,
		.end		= I2C3_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};
static struct resource fh_i2c_resources_4[] = {
	{
		.start		= I2C4_REG_BASE,
		.end		= I2C4_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},

	{
		.start		= I2C4_IRQ,
		.end		= I2C4_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};

static struct resource fh_rtc_resources[] = {
	{
		.start		= RTC_REG_BASE,
		.end		= RTC_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},

	{
		.start		= RTC_IRQ,
		.end		= RTC_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};

static struct fh_gpio_chip fh_gpio0_chip = {
	.chip = {
		.owner = THIS_MODULE,
		.label = "FH_GPIO0",
		.base = 0,
		.ngpio = 32,
	},
};

static struct fh_gpio_chip fh_gpio1_chip = {
	.chip = {
		.owner = THIS_MODULE,
		.label = "FH_GPIO1",
		.base = 32,
		.ngpio = 32,
	},
};

static struct fh_gpio_chip fh_gpio2_chip = {
	.chip = {
		.owner = THIS_MODULE,
		.label = "FH_GPIO2",
		.base = 64,
		.ngpio = 32,
	},
};

static struct fh_pwm_data pwm_data = {
	.npwm = 14,
};

static struct resource fh_sadc_resources[] = {
	{
		.start		= SADC_REG_BASE,
		.end		= SADC_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},
	{
		.start		= SADC_IRQ,
		.end		= SADC_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};

static struct resource fh_aes_resources[] = {
	{
		.start		= AES_REG_BASE,
		.end		= AES_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},
	{
		.start		= AES_IRQ,
		.end		= AES_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};

static struct resource fh_efuse_resources[] = {
	{
		.start		= EFUSE_REG_BASE,
		.end		= EFUSE_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},
};



static struct resource fh_axi_dma_resources[] = {
	{
		.start          = (DMAC0_REG_BASE),
		.end            = (DMAC0_REG_BASE) + SZ_16K - 1,
		.flags          = IORESOURCE_MEM,
	},
	{
		.start          = DMAC0_IRQ,
		.end            = DMAC0_IRQ,
		.flags          = IORESOURCE_IRQ,
	},
};


static struct resource fh_spi0_resources[] = {
	{
		.start		= SPI0_REG_BASE,
		.end		= SPI0_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},
	{
		.start		= SPI0_IRQ,
		.end		= SPI0_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};

static struct resource fh_spi1_resources[] = {
	{
		.start		= SPI1_REG_BASE,
		.end		= SPI1_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},
	{
		.start		= SPI1_IRQ,
		.end		= SPI1_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};

static struct resource fh_spi2_resources[] = {
	{
		.start		= SPI2_REG_BASE,
		.end		= SPI2_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
		.name = "fh spi2 mem",
	},
	{
		.start		= SPI2_IRQ,
		.end		= SPI2_IRQ,
		.flags		= IORESOURCE_IRQ,
		.name = "fh spi2 irq",
	},
};

static struct resource fh_spi3_resources[] = {
	{
		.start		= SPI3_REG_BASE,
		.end		= SPI3_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
		.name = "fh spi3 mem",
	},
	{
		.start		= SPI3_IRQ,
		.end		= SPI3_IRQ,
		.flags		= IORESOURCE_IRQ,
		.name = "fh spi3 irq",
	},
};

static struct resource fh_usb_resources[] = {
	{
		.start		= USBC_REG_BASE,
		.end		= USBC_REG_BASE + SZ_1M - 1,
		.flags		= IORESOURCE_MEM,
	},
	{
		.start		= USBC_IRQ,
		.end		= USBC_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};
static struct resource fh_hash_resources[] = {
	{
		.start		= (HASH_REG_BASE),
		.end		= (HASH_REG_BASE) + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},
	{
		.start		= HASH_IRQ,
		.end		= HASH_IRQ,
		.flags		= IORESOURCE_IRQ,
	}
};

static unsigned int  fh_mci_sys_card_detect_fixed(struct fhmci_host *host)
{
	return 0;
}

struct fh_mci_board fh_mci = {
	.num_slots = 1,
	.get_cd = fh_mci_sys_card_detect_fixed,
	.bus_hz = 50000000,
	.detect_delay_ms = 200,
	.caps = MMC_CAP_4_BIT_DATA,
	/*8:180  degree*/
	.drv_degree = 4,
	.sam_degree = 0,
	.rescan_max_num = 2,
};

struct fh_mci_board fh_mci_sd = {
	.num_slots = 1,
	.bus_hz = 50000000,
	.detect_delay_ms = 200,
	.caps = MMC_CAP_4_BIT_DATA,
	/*8:180  degree*/
	.drv_degree = 4,
	.sam_degree = 0,
};

static struct platform_device fh_gmac_device = {
	.name           = "fh_qos_gmac",
	.id             = 0,
	.num_resources  = ARRAY_SIZE(fh_gmac_resources),
	.resource       = fh_gmac_resources,
	.dev = {
		.coherent_dma_mask = DMA_BIT_MASK(32),
		.platform_data = &fh_gmac_data,
	},
};

struct platform_device fh_sd0_device = {
	.name			= "fh_mci",
	.id			= 0,
	.num_resources		= ARRAY_SIZE(fh_sdc0_resources),
	.resource		= fh_sdc0_resources,
	.dev			= {
	.coherent_dma_mask	= DMA_BIT_MASK(32),
	.platform_data = &fh_mci_sd,
	}
};

struct platform_device fh_sd1_device = {
	.name			= "fh_mci",
	.id			= 1,
	.num_resources		= ARRAY_SIZE(fh_sdc1_resources),
	.resource		= fh_sdc1_resources,
	.dev			= {
	.coherent_dma_mask	= DMA_BIT_MASK(32),
	.platform_data = &fh_mci_sd,
	}
};

struct fh_sadc_platform_data fh_sadc_data = {
	.ref_vol = 1800,
	.active_bit = 0xfff,
};

static struct platform_device fh_sadc_device = {
	.name			= "fh_sadc",
	.id			= 0,
	.num_resources		= ARRAY_SIZE(fh_sadc_resources),
	.resource		= fh_sadc_resources,
	.dev			= {
	.platform_data = &fh_sadc_data,
	},
};

static struct platform_device fh_uart0_device = {
	.name				= "ttyS",
	.id			= 0,
	.num_resources		= ARRAY_SIZE(fh_uart0_resources),
	.resource		= fh_uart0_resources,
	.dev.platform_data	= &fh_uart_platform_data[0],
};

static struct platform_device fh_uart1_device = {
	.name				= "ttyS",
	.id					= 1,
	.num_resources		= ARRAY_SIZE(fh_uart1_resources),
	.resource			= fh_uart1_resources,
	.dev.platform_data	= &fh_uart_platform_data[1],
};

static struct platform_device fh_uart2_device = {
	.name				= "ttyS",
	.id					= 2,
	.num_resources		= ARRAY_SIZE(fh_uart2_resources),
	.resource			= fh_uart2_resources,
	.dev.platform_data	= &fh_uart_platform_data[2],
};

static struct platform_device fh_uart3_device = {
	.name				= "ttyS",
	.id					= 3,
	.num_resources		= ARRAY_SIZE(fh_uart3_resources),
	.resource			= fh_uart3_resources,
	.dev.platform_data	= &fh_uart_platform_data[3],
};

static struct platform_device fh_pinctrl_device = {
	.name			= "fh_pinctrl",
	.id			= 0,
};

static struct platform_device fh_i2c0_device = {
	.name			= "fh_i2c",
	.id			= 0,
	.num_resources		= ARRAY_SIZE(fh_i2c_resources_0),
	.resource		= fh_i2c_resources_0,
};

static struct platform_device fh_i2c1_device = {
	.name			= "fh_i2c",
	.id			= 1,
	.num_resources		= ARRAY_SIZE(fh_i2c_resources_1),
	.resource		= fh_i2c_resources_1,
};

static struct platform_device fh_i2c2_device = {
	.name			= "fh_i2c",
	.id			= 2,
	.num_resources		= ARRAY_SIZE(fh_i2c_resources_2),
	.resource		= fh_i2c_resources_2,
};

static struct platform_device fh_i2c3_device = {
	.name			= "fh_i2c",
	.id			= 3,
	.num_resources		= ARRAY_SIZE(fh_i2c_resources_3),
	.resource		= fh_i2c_resources_3,
};

static struct platform_device fh_i2c4_device = {
	.name			= "fh_i2c",
	.id			= 4,
	.num_resources		= ARRAY_SIZE(fh_i2c_resources_4),
	.resource		= fh_i2c_resources_4,
};

static struct fh_rtc_plat_data rtc_plat_data = {
	.lut_cof = 70,
	.lut_offset = 0xf7,
	.tsensor_cp_default_out = 0x9a6,
	.clk_name = "rtc_pclk_gate",
};

static struct platform_device fh_rtc_device = {
	.name			= "fh_rtc",
	.id			= 0,
	.num_resources		= ARRAY_SIZE(fh_rtc_resources),
	.resource		= fh_rtc_resources,
	.dev.platform_data	= &rtc_plat_data,
};

static struct resource fh_i2s_resources[] = {
	{
		.start		= I2S_REG_BASE,
		.end		= I2S_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},
	{
		.start		= ACW_REG_BASE,
		.end		= ACW_REG_BASE + SZ_16K - 1,
		.flags		= IORESOURCE_MEM,
	},
	{
		.start		= I2S0_IRQ,
		.end		= I2S0_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};

static struct fh_i2s_platform_data fh_i2s_data = {
	.dma_capture_channel = 4,
	.dma_playback_channel = 5,
	.dma_master = 0,
	.dma_rx_hs_num = 10,
	.dma_tx_hs_num = 11,
	.dma_master = 0,
	.clk = "i2s_clk",
	.acodec_mclk = "ac_clk",
};

static struct platform_device fh_i2s_device = {
	.name			= "fh_audio",
	.id			= 0,
	.num_resources		= ARRAY_SIZE(fh_i2s_resources),
	.resource		= fh_i2s_resources,
	.dev			= {
		.platform_data = &fh_i2s_data,
	},
};

static struct platform_device fh_gpio0_device = {
	.name			= GPIO_NAME,
	.id				= 0,
	.num_resources	= ARRAY_SIZE(fh_gpio0_resources),
	.resource		= fh_gpio0_resources,
	.dev			= {
		.platform_data = &fh_gpio0_chip,
	},
};

static struct platform_device fh_gpio1_device = {
	.name			= GPIO_NAME,
	.id				= 1,
	.num_resources	= ARRAY_SIZE(fh_gpio1_resources),
	.resource		= fh_gpio1_resources,
	.dev			= {
		.platform_data = &fh_gpio1_chip,
	},
};

static struct platform_device fh_gpio2_device = {
	.name			= GPIO_NAME,
	.id				= 2,
	.num_resources	= ARRAY_SIZE(fh_gpio2_resources),
	.resource		= fh_gpio2_resources,
	.dev			= {
		.platform_data = &fh_gpio2_chip,
	},
};

#ifdef CONFIG_CRYPTO_DEV_FH_AES_TEE
static int aes_uuid[11] = {0xdd00d7bd, 0xe9e3, 0x4dcb,
		0xad, 0xbc, 0xda, 0x54, 0xa7, 0x1b, 0x9b, 0x65};
#endif

#ifdef CONFIG_CRYPTO_DEV_FH_CESA
static struct platform_device fh_cesa_device = {
	.name			= "fh_cesa",
	.id			= 0,
	.num_resources		= ARRAY_SIZE(fh_aes_resources),
	.resource			= fh_aes_resources,
	.dev			= {
#ifdef CONFIG_CRYPTO_DEV_FH_AES_TEE
	.platform_data = aes_uuid,
#else
	.platform_data = NULL,
#endif
	},
};
#else
static struct platform_device fh_aes_device = {
	.name			= "fh_aes",
	.id			= 0,
	.num_resources		= ARRAY_SIZE(fh_aes_resources),
	.resource		= fh_aes_resources,
	.dev			= {
#ifdef CONFIG_CRYPTO_DEV_FH_AES_TEE
	.platform_data = aes_uuid,
#else
	.platform_data = NULL,
#endif
	},
};
#endif

#ifdef CONFIG_FH_EFUSE_TEE
static int efuse_uuid[11] = {0x796ad1ff, 0x5565, 0x4141,
		0x9a, 0x1c, 0x29, 0x00, 0x20, 0xaa, 0x9f, 0x16};
#endif

static struct fh_efuse_platform_data fh_efuse_plat_data = {
	.efuse_support_flag = CRYPTO_CPU_SET_KEY |
	CRYPTO_EX_MEM_SET_KEY |
	CRYPTO_EX_MEM_SWITCH_KEY |
	CRYPTO_EX_MEM_4_ENTRY_1_KEY |
	CRYPTO_EX_MEM_INDEP_POWER,
#ifdef CONFIG_FH_EFUSE_TEE
	.optee_uuid = efuse_uuid,
#endif
};



#define FH_SPI0_CS0	(6)
#define FH_SPI1_CS0	(14)
#define FH_SPI1_CS1	(0)
#define FH_SPI1_CS2	(1)
#define FH_SPI1_CS3	(2)
#define FH_SPI3_CS0	(65)

#define SPI0_FIFO_DEPTH				(128)
#define SPI0_CLK_IN				(200000000)
#define SPI0_MAX_SLAVE_NO			(1)
#define SPI0_DMA_RX_CHANNEL			(0)
#define SPI0_DMA_TX_CHANNEL			(1)

#define SPI1_FIFO_DEPTH				(64)
#define SPI1_CLK_IN				(100000000)
#define SPI1_MAX_SLAVE_NO			(4)
#define SPI1_DMA_RX_CHANNEL			(2)
#define SPI1_DMA_TX_CHANNEL			(3)

#define SPI2_CLK_IN				(100000000)
#define SPI2_DMA_RX_CHANNEL			(4)
#define SPI2_DMA_TX_CHANNEL			(5)

#define SPI3_FIFO_DEPTH				(64)
#define SPI3_CLK_IN					(100000000)
#define SPI3_MAX_SLAVE_NO			(1)
#define SPI3_DMA_RX_CHANNEL			(6)
#define SPI3_DMA_TX_CHANNEL			(7)

/* SPI_TRANSFER_USE_DMA */
static struct fh_spi_platform_data fh_spi0_data = {
	.bus_no = 0,
	.apb_clock_in = SPI0_CLK_IN,
	.clock_source = {100000000, 150000000, 200000000},
	.clock_source_num = 3,
	.slave_max_num = SPI0_MAX_SLAVE_NO,
	.cs_data[0].GPIO_Pin = FH_SPI0_CS0,
	.cs_data[0].name = "spi0_cs0",
	.clk_name = "spi0_clk",
	.dma_transfer_enable = SPI_TRANSFER_USE_DMA,
	.external_ecc_enable = 0,
	.rx_dma_channel = SPI0_DMA_RX_CHANNEL,
	.tx_dma_channel = SPI0_DMA_TX_CHANNEL,
	.rx_handshake_num = 4,
	.tx_handshake_num = 5,
	/*dma use inc mode could move data by burst mode...*/
	/*or move data use single mode with low efficient*/
	.ctl_wire_support = ONE_WIRE_SUPPORT | DUAL_WIRE_SUPPORT |
	MULTI_WIRE_SUPPORT,
};

static struct fh_spi_platform_data fh_spi1_data = {
	.bus_no = 1,
	.apb_clock_in = SPI1_CLK_IN,
	.clock_source = {SPI1_CLK_IN},
	.clock_source_num = 1,
	.slave_max_num = SPI1_MAX_SLAVE_NO,
	.cs_data[0].GPIO_Pin = FH_SPI1_CS0,
	.cs_data[0].name = "spi1_cs0",
	.cs_data[1].GPIO_Pin = FH_SPI1_CS1,
	.cs_data[1].name = "spi1_cs1",
	.cs_data[2].GPIO_Pin = FH_SPI1_CS2,
	.cs_data[2].name = "spi1_cs2",
	.cs_data[3].GPIO_Pin = FH_SPI1_CS3,
	.cs_data[3].name = "spi1_cs3",
	.clk_name = "spi1_clk",
	.ctl_wire_support = 0,
};

static struct fh_spi_platform_data fh_spi2_data = {
	.apb_clock_in = SPI2_CLK_IN,
	.dma_transfer_enable = 0,
	.rx_handshake_num = 14,
	.clk_name = "spi2_clk",
	.ctl_wire_support = 0,
	.rx_dma_channel = SPI2_DMA_RX_CHANNEL,
};

static struct fh_spi_platform_data fh_spi3_data = {
	.bus_no = 3,
	.apb_clock_in = SPI3_CLK_IN,
	.clock_source = {SPI3_CLK_IN},
	.clock_source_num = 1,
	.slave_max_num = SPI3_MAX_SLAVE_NO,
	.cs_data[0].GPIO_Pin = FH_SPI3_CS0,
	.cs_data[0].name = "spi3_cs0",
	.clk_name = "spi3_clk",
	.ctl_wire_support = 0,
};

static struct platform_device fh_efuse_device = {
	.name			= "fh_efuse",
	.id			= 0,
	.num_resources		= ARRAY_SIZE(fh_efuse_resources),
	.resource		= fh_efuse_resources,
	.dev			= {
		.platform_data = &fh_efuse_plat_data,
	},
};

struct fh_axi_dma_platform_data axi_dma_plat_data = {
	.chan_priority  = CHAN_PRIORITY_ASCENDING,
	.clk_name       = "ahb_clk",
	.spdup.spdup_flag = AXI_SPD_UP_ACTIVE,
	.spdup.spdup_ctl_low = CH_CTL_L_AR_CACHE(0) | CH_CTL_L_AW_CACHE(0),
	.spdup.spdup_ctl_high = CH_CTL_H_ARLEN_EN(0) | CH_CTL_H_ARLEN(0)
	| CH_CTL_H_AWLEN_EN(0) | CH_CTL_H_AWLEN(0),
	.spdup.spdup_cfg_low = 0,
	.spdup.spdup_cfg_high = CH_CFG_H_DST_OSR_LMT(0)
	| CH_CFG_H_SRC_OSR_LMT(0),

};

static struct platform_device fh_axi_dma_device = {
	.name                   = "fh_axi_dmac",
	.id                     = 0,
	.num_resources          = ARRAY_SIZE(fh_axi_dma_resources),
	.resource               = fh_axi_dma_resources,
	.dev                    = {
		.platform_data = &axi_dma_plat_data,
	},
};

static struct platform_device fh_spi0_device = {
	.name			= "fh_spi",
	.id			= 0,
	.num_resources		= ARRAY_SIZE(fh_spi0_resources),
	.resource		= fh_spi0_resources,
	.dev			= {
		.platform_data = &fh_spi0_data,
	},
};

static struct platform_device fh_spi1_device = {
	.name			= "fh_spi",
	.id			= 1,
	.num_resources		= ARRAY_SIZE(fh_spi1_resources),
	.resource		= fh_spi1_resources,
	.dev			= {
		.platform_data = &fh_spi1_data,
	},
};

static struct platform_device fh_spi2_device = {
	.name			= "fh_spi_slave",
	.id			= 0,
	.num_resources		= ARRAY_SIZE(fh_spi2_resources),
	.resource		= fh_spi2_resources,
	.dev			= {
		.platform_data = &fh_spi2_data,
	},
};

static struct platform_device fh_spi3_device = {
	.name			= "fh_spi",
	.id			= 3,
	.num_resources		= ARRAY_SIZE(fh_spi3_resources),
	.resource		= fh_spi3_resources,
	.dev			= {
		.platform_data = &fh_spi3_data,
	},
};

#if defined(CONFIG_FH_PERF_MON) || defined(CONFIG_FH_PERF_MON_V2)
static struct platform_device fh_perf_device = {
	.name	= "fh_perf_mon",
	.id	= 0,
	.num_resources	= ARRAY_SIZE(fh_perf_resources),
	.resource	= fh_perf_resources,
	.dev	= {
		.platform_data = NULL,
	},
};
#endif

#ifdef CONFIG_FH_STEPMOTOR
static struct platform_device fh_stepmotor_device0 = {
	.name                   = "fh_stepmotor",
	.id     = 0,
	.num_resources          = ARRAY_SIZE(fh_stepmotor_resources0),
	.resource               = fh_stepmotor_resources0,
	.dev                    = {
	.platform_data = NULL,
	},
};

static struct platform_device fh_stepmotor_device1 = {
	.name                   = "fh_stepmotor",
	.id     = 1,
	.num_resources          = ARRAY_SIZE(fh_stepmotor_resources1),
	.resource               = fh_stepmotor_resources1,
	.dev                    = {
	.platform_data = NULL,
	},
};
#endif


static struct fh_wdt_platform_data fh_wdt_data = {
	.mode   = MODE_DISCRETE,
};

struct platform_device fh_wdt_device = {
	.name			= "fh_wdt",
	.id				= 0,
	.num_resources	= ARRAY_SIZE(fh_wdt_resources),
	.resource		= fh_wdt_resources,
	.dev			= {
		.platform_data = &fh_wdt_data,
	}
};

static struct platform_device fh_pwm_device = {
	.name			= "fh_pwm",
	.id				= 0,
	.num_resources	= ARRAY_SIZE(fh_pwm_resources),
	.resource		= fh_pwm_resources,
	.dev			= {
		.platform_data = &pwm_data,
	},
};

static struct fh_usb_platform_data fh_usb_data = {
	.dr_mode  = "host",
	.vbus_pwren = 47,
};

struct platform_device fh_usb_device = {
	.name			= "fh_usb",
	.id				= 0,
	.num_resources	= ARRAY_SIZE(fh_usb_resources),
	.resource		= fh_usb_resources,
	.dev			= {
		.platform_data = &fh_usb_data,
	}
};

#ifdef CONFIG_FH_TSENSOR
struct platform_device fh_tsensor_device = {
	.name			= "fh_tsensor",
	.id				= 0,
};
#endif

static struct platform_device fh_hash_device = {
	.name		= "fh_hash",
	.num_resources	= ARRAY_SIZE(fh_hash_resources),
	.resource	= fh_hash_resources,
};
static struct platform_device *fh8862_devices[] __initdata = {
	&fh_uart0_device,
	&fh_uart1_device,
	&fh_uart2_device,
	&fh_uart3_device,
	&fh_pinctrl_device,
	&fh_i2c0_device,
	&fh_i2c1_device,
	&fh_i2c2_device,
	&fh_i2c3_device,
	&fh_i2c4_device,
	&fh_rtc_device,
	&fh_sd0_device,
	&fh_sd1_device,
	&fh_sadc_device,
	&fh_gmac_device,
	&fh_gpio0_device,
	&fh_gpio1_device,
	&fh_gpio2_device,
#ifdef CONFIG_CRYPTO_DEV_FH_CESA
	&fh_cesa_device,
#else
	&fh_aes_device,
#endif
	&fh_efuse_device,
	&fh_axi_dma_device,
	&fh_spi0_device,
	&fh_spi1_device,
	&fh_spi2_device,
	&fh_spi3_device,
	&fh_i2s_device,
	&fh_pwm_device,
	&fh_wdt_device,
	&fh_usb_device,
#if defined(CONFIG_FH_PERF_MON) || defined(CONFIG_FH_PERF_MON_V2)
	&fh_perf_device,
#endif
#ifdef CONFIG_FH_STEPMOTOR
	&fh_stepmotor_device0,
	&fh_stepmotor_device1,
#endif
#ifdef CONFIG_FH_TSENSOR
	&fh_tsensor_device,
#endif
	&fh_hash_device,
};

static struct mtd_partition fh_sf_parts[] = {
	{
		/* head & Ramboot */
		.name		= "bootstrap",
		.offset		= 0,
		.size		= SZ_256K,
		.mask_flags	= MTD_WRITEABLE, /* force read-only */
	}, {
		/* Ramboot & U-Boot environment */
		.name		= "uboot-env",
		.offset		= MTDPART_OFS_APPEND,
		.size		= SZ_64K,
		.mask_flags	= MTD_WRITEABLE, /* force read-only */
	}, {
		/* U-Boot */
		.name		= "uboot",
		.offset		= MTDPART_OFS_APPEND,
		.size		= SZ_256K,
		.mask_flags	= MTD_WRITEABLE, /* force read-only */
	}, {
		.name		= "kernel",
		.offset		= MTDPART_OFS_APPEND,
		.size		= SZ_4M,
		.mask_flags	= 0,
	}, {
		.name		= "rootfs",
		.offset		= MTDPART_OFS_APPEND,
		.size		= SZ_8M,
		.mask_flags	= 0,
	}, {
		.name		= "app",
		.offset		= MTDPART_OFS_APPEND,
		.size		= MTDPART_SIZ_FULL,
		.mask_flags	= 0,
	}
	/* mtdparts=
	* spi_flash:256k(bootstrap),
	* 64k(u-boot-env),
	* 192k(u-boot),4M(kernel),
	* 8M(rootfs),
	* -(app) */
	/* two blocks with bad block table (and mirror) at the end */
};
#ifdef CONFIG_MTD_SPI_NAND
static struct mtd_partition fh_sf_nand_parts[] = {
	{
		/* head & Ramboot */
		.name		= "bootstrap",
		.offset		= 0,
		.size		= SZ_256K,
		.mask_flags	= MTD_WRITEABLE, /* force read-only */
	}, {
		.name		= "uboot-env",
		.offset		= MTDPART_OFS_APPEND,
		.size		= SZ_256K,
		.mask_flags	= MTD_WRITEABLE,
	}, {
		.name		= "uboot",
		.offset		= MTDPART_OFS_APPEND,
		.size		= SZ_512K,
		.mask_flags	= MTD_WRITEABLE,
	}, {
		.name		= "kernel",
		.offset		= MTDPART_OFS_APPEND,
		.size		= SZ_4M,
		.mask_flags	= 0,
	}, {
		.name		= "rootfs",
		.offset		= MTDPART_OFS_APPEND,
		.size		= SZ_8M,
		.mask_flags	= 0,
	}, {
		.name		= "app",
		.offset		= MTDPART_OFS_APPEND,
		.size		= MTDPART_SIZ_FULL,
		.mask_flags	= 0,
	}
	/* mtdparts=
	 * spi0.0:64k(bootstrap),
	 * 64k(u-boot-env),
	 * 192k(u-boot),
	 * 4M(kernel),
	 * 8M(rootfs),
	 * -(app)
	 * two blocks with bad block table (and mirror) at the end
	 */
};
#endif

static struct flash_platform_data fh_flash_platform_data  = {
	.name		= "spi_flash",
	.parts		= fh_sf_parts,
	.nr_parts	= ARRAY_SIZE(fh_sf_parts),
};
#ifdef CONFIG_MTD_SPI_NAND
static struct flash_platform_data fh_nandflash_platform_data  = {
	.name		= "spi_nandflash",
	.parts		= fh_sf_nand_parts,
	.nr_parts	= ARRAY_SIZE(fh_sf_nand_parts),
};
#endif

static struct spi_board_info fh_spi_devices[] = {
	{
		.modalias		= "spidev",
		.bus_num		= 1,
		.chip_select	= 0,
		.max_speed_hz	= 5000000,
		.mode			= SPI_MODE_3,
	},
	{
		.modalias		= "spidev",
		.bus_num		= 1,
		.chip_select	= 1,
		.max_speed_hz	= 5000000,
		.mode			= SPI_MODE_3,
	},
	{
		.modalias		= "spidev",
		.bus_num		= 1,
		.chip_select	= 2,
		.max_speed_hz	= 5000000,
		.mode			= SPI_MODE_3,
	},
	{
		.modalias		= "spidev",
		.bus_num		= 1,
		.chip_select	= 3,
		.max_speed_hz	= 5000000,
		.mode			= SPI_MODE_3,
	},
#ifdef CONFIG_MTD_SPI_NAND
	{
		.modalias		= "spi-nand",
		.bus_num		= 0,
		.chip_select	= 0,
		.max_speed_hz	= 50000000,
		.mode			= SPI_MODE_3,
		.platform_data	 = &fh_nandflash_platform_data,
	},
#endif
	{
		.modalias        = "m25p80",
		.bus_num         = 0,
		.chip_select     = 0,
		/* multi wire should adapt spi para 'ctl_wire_support'*/
		.mode            = SPI_MODE_3  | SPI_RX_DUAL,
		.max_speed_hz    = 50000000,
		.platform_data   = &fh_flash_platform_data,
	},

};

extern void early_print(const char *str, ...);

static void __init fh_console_pre_init(struct fh_platform_uart *plat, int num)
{
	int idx = 0;

	for (; idx < num; idx++) {
		struct uart_port *port;

		port            = &fh_serial_ports[idx];
		port->mapbase   = plat[idx].mapbase;
		port->fifosize  = plat[idx].fifo_size;
		port->uartclk   = plat[idx].uartclk;
		port->flags     = plat[idx].flags;

		switch (idx) {
		case 0:
			port->membase = (unsigned char *)VA_UART0_REG_BASE;
			break;
		case 1:
			port->membase = (unsigned char *)VA_UART1_REG_BASE;
			break;
		case 2:
			port->membase = (unsigned char *)VA_UART2_REG_BASE;
			break;
		case 3:
			port->membase = (unsigned char *)VA_UART3_REG_BASE;
			break;
		default:
			break;
		}
	}
}

static void __init fh8862_map_io(void)
{
	fullhan_map_io();
	fh_console_pre_init(fh_uart_platform_data,
			ARRAY_SIZE(fh_uart_platform_data));
}


static __init void fh8862_board_init(void)
{
	platform_add_devices(fh8862_devices,
			ARRAY_SIZE(fh8862_devices));
	spi_register_board_info(fh_spi_devices, ARRAY_SIZE(fh_spi_devices));
}
void  __init fh_timer_init_no_of(unsigned int iovbase,
	unsigned int irqno);

static void __init fh8862_init_early(void)
{
	fh_pmu_init();
	fh_pinctrl_init(VA_PIN_REG_BASE);
}

static void __init fh_time_init(void)
{
	unsigned int vtimerbase = (unsigned int)ioremap(TMR0_REG_BASE, SZ_4K);

	fh_clk_init();
	fh_timer_init_no_of(vtimerbase, TMR0_IRQ);

}
static void fh8862_restart
				(enum reboot_mode mode, const char *cmd)
{
	fh_pmu_restart();
}
static void __init fh_gic_no_of_init(void)
{

	void * p_gicd = ioremap(GICD_REG_BASE,SZ_16K);
	void * p_gicc = ioremap(GICC_REG_BASE,SZ_16K);
	gic_init(0, -1, p_gicd,p_gicc);
}

#ifdef CONFIG_HAVE_ARM_ARCH_TIMER
int  arch_timer_noof_init(u32 freq,
	u32 ppilist[4], int alwayson, int suspendstop);
static void  __init init_arch_timer_noof(void)
{
	/* arm cortexa7 standard arch-timer ppi id */
	u32 ppilist[4] = {13+16, 14+16, 11+16, 10+16};

	fh_clk_init();
	arch_timer_noof_init(24*1000*1000, ppilist, 0, 0);
}
#endif

MACHINE_START(FH8862, "FH8862")
	.atag_offset	= 0x100,
	.map_io		= fh8862_map_io,
	.init_irq	= fh_gic_no_of_init,
#ifdef CONFIG_HAVE_ARM_ARCH_TIMER
	.init_time	= init_arch_timer_noof,
#else
	.init_time      = fh_time_init,
#endif
#ifdef CONFIG_SMP
	.smp_init = fh_smp_init,
#endif
	.init_machine	= fh8862_board_init,
	.init_early	= fh8862_init_early,
	.restart	= fh8862_restart,
MACHINE_END



